/*!
 * \file HftStraBaseCtx.h
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief HFT策略基础上下文头文件
 * 
 * 本文件定义了HFT（高频交易）策略基础上下文类，是所有HFT策略上下文的基类。
 * 实现了IHftStraCtx接口和ITrdNotifySink接口，提供HFT策略运行所需的基础功能，
 * 包括Level2数据处理、高频交易、订单管理、持仓管理、资金管理等核心功能。
 */
#pragma once

#include "../Includes/FasterDefs.h"
#include "../Includes/IHftStraCtx.h"
#include "../Share/BoostFile.hpp"
#include "../Share/fmtlib.h"

#include <boost/circular_buffer.hpp>

#include "ITrdNotifySink.h"

NS_WTP_BEGIN

class WtHftEngine;
class TraderAdapter;

/**
 * @class HftStraBaseCtx
 * @brief HFT策略基础上下文类
 * 
 * HFT策略基础上下文类，继承自IHftStraCtx和ITrdNotifySink接口，为所有HFT策略提供基础功能。
 * 
 * 主要功能包括：
 * - Level2数据处理：支持委托队列、委托明细、成交明细等高频数据
 * - 高频交易：提供买卖、开平仓等交易接口，支持FAK/FOK等订单类型
 * - 订单管理：订单状态跟踪、撤单、订单标签管理
 * - 持仓管理：实时持仓跟踪、盈亏计算、持仓明细管理
 * - 资金管理：资金状况跟踪、手续费统计
 * - 数据订阅：支持tick、Level2数据的主动订阅
 * - 日志记录：交易、平仓、资金等日志记录
 * - 用户数据：支持策略自定义数据的存储和读取
 * 
 * @note 这是一个基类，具体的HFT策略上下文类需要继承此类
 * @see IHftStraCtx, ITrdNotifySink, HftStraContext, WtHftEngine
 */
class HftStraBaseCtx : public IHftStraCtx, public ITrdNotifySink
{
public:
	/**
	 * @brief 构造函数
	 * 
	 * 创建HFT策略基础上下文实例
	 * 
	 * @param engine HFT引擎指针
	 * @param name 策略名称
	 * @param bAgent 是否为代理模式
	 */
	HftStraBaseCtx(WtHftEngine* engine, const char* name, bool bAgent);
	
	/**
	 * @brief 析构函数
	 * 
	 * 清理资源
	 */
	virtual ~HftStraBaseCtx();

	/**
	 * @brief 设置交易适配器
	 * 
	 * @param trader 交易适配器指针
	 */
	void setTrader(TraderAdapter* trader);

public:
	//////////////////////////////////////////////////////////////////////////
	//IHftStraCtx 接口
	/**
	 * @brief 获取上下文ID
	 * 
	 * @return 上下文ID
	 */
	virtual uint32_t id() override;

	/**
	 * @brief 初始化回调
	 */
	virtual void on_init() override;

	/**
	 * @brief Tick数据回调
	 * 
	 * @param stdCode 标准合约代码
	 * @param newTick 新Tick数据
	 */
	virtual void on_tick(const char* stdCode, WTSTickData* newTick) override;

	/**
	 * @brief 委托队列数据回调
	 * 
	 * @param stdCode 标准合约代码
	 * @param newOrdQue 新委托队列数据
	 */
	virtual void on_order_queue(const char* stdCode, WTSOrdQueData* newOrdQue) override;

	/**
	 * @brief 委托明细数据回调
	 * 
	 * @param stdCode 标准合约代码
	 * @param newOrdDtl 新委托明细数据
	 */
	virtual void on_order_detail(const char* stdCode, WTSOrdDtlData* newOrdDtl) override;

	/**
	 * @brief 成交明细数据回调
	 * 
	 * @param stdCode 标准合约代码
	 * @param newTrans 新成交明细数据
	 */
	virtual void on_transaction(const char* stdCode, WTSTransData* newTrans) override;

	/**
	 * @brief K线数据回调
	 * 
	 * @param stdCode 标准合约代码
	 * @param period K线周期
	 * @param times K线倍数
	 * @param newBar 新K线数据
	 */
	virtual void on_bar(const char* stdCode, const char* period, uint32_t times, WTSBarStruct* newBar) override;

	/**
	 * @brief 交易时段开始回调
	 * 
	 * @param uTDate 交易日期
	 */
	virtual void on_session_begin(uint32_t uTDate) override;

	/**
	 * @brief 交易时段结束回调
	 * 
	 * @param uTDate 交易日期
	 */
	virtual void on_session_end(uint32_t uTDate) override;

	/**
	 * @brief 撤单
	 * 
	 * @param localid 本地订单ID
	 * @return 是否成功
	 */
	virtual bool stra_cancel(uint32_t localid) override;

	/**
	 * @brief 批量撤单
	 * 
	 * @param stdCode 标准合约代码
	 * @param isBuy 是否买单
	 * @param qty 撤单数量
	 * @return 订单ID列表
	 */
	virtual OrderIDs stra_cancel(const char* stdCode, bool isBuy, double qty) override;

	/**
	 * @brief 下单接口：买入
	 * 
	 * @param stdCode 合约代码
	 * @param price 下单价格，0表示市价单
	 * @param qty 下单数量
	 * @param userTag 用户标签
	 * @param flag 下单标志：0-normal，1-fak，2-fok，默认0
	 * @return 订单ID列表
	 */
	virtual OrderIDs stra_buy(const char* stdCode, double price, double qty, const char* userTag, int flag = 0) override;

	/**
	 * @brief 下单接口：卖出
	 * 
	 * @param stdCode 合约代码
	 * @param price 下单价格，0表示市价单
	 * @param qty 下单数量
	 * @param userTag 用户标签
	 * @param flag 下单标志：0-normal，1-fak，2-fok，默认0
	 * @return 订单ID列表
	 */
	virtual OrderIDs stra_sell(const char* stdCode, double price, double qty, const char* userTag, int flag = 0) override;

	/**
	 * @brief 下单接口：开多
	 * 
	 * @param stdCode 合约代码
	 * @param price 下单价格，0表示市价单
	 * @param qty 下单数量
	 * @param userTag 用户标签
	 * @param flag 下单标志：0-normal，1-fak，2-fok
	 * @return 本地订单ID
	 */
	virtual uint32_t	stra_enter_long(const char* stdCode, double price, double qty, const char* userTag, int flag = 0) override;

	/**
	 * @brief 下单接口：开空
	 * 
	 * @param stdCode 合约代码
	 * @param price 下单价格，0表示市价单
	 * @param qty 下单数量
	 * @param userTag 用户标签
	 * @param flag 下单标志：0-normal，1-fak，2-fok
	 * @return 本地订单ID
	 */
	virtual uint32_t	stra_enter_short(const char* stdCode, double price, double qty, const char* userTag, int flag = 0) override;

	/**
	 * @brief 下单接口：平多
	 * 
	 * @param stdCode 合约代码
	 * @param price 下单价格，0表示市价单
	 * @param qty 下单数量
	 * @param userTag 用户标签
	 * @param isToday 是否今仓，默认false
	 * @param flag 下单标志：0-normal，1-fak，2-fok，默认0
	 * @return 本地订单ID
	 */
	virtual uint32_t	stra_exit_long(const char* stdCode, double price, double qty, const char* userTag, bool isToday = false, int flag = 0) override;

	/**
	 * @brief 下单接口：平空
	 * 
	 * @param stdCode 合约代码
	 * @param price 下单价格，0表示市价单
	 * @param qty 下单数量
	 * @param userTag 用户标签
	 * @param isToday 是否今仓，默认false
	 * @param flag 下单标志：0-normal，1-fak，2-fok，默认0
	 * @return 本地订单ID
	 */
	virtual uint32_t	stra_exit_short(const char* stdCode, double price, double qty, const char* userTag, bool isToday = false, int flag = 0) override;

	/**
	 * @brief 获取品种信息
	 * 
	 * @param stdCode 标准合约代码
	 * @return 品种信息
	 */
	virtual WTSCommodityInfo* stra_get_comminfo(const char* stdCode) override;

	/**
	 * @brief 获取K线数据
	 * 
	 * @param stdCode 标准合约代码
	 * @param period K线周期
	 * @param count 数据条数
	 * @return K线数据切片
	 */
	virtual WTSKlineSlice* stra_get_bars(const char* stdCode, const char* period, uint32_t count) override;

	/**
	 * @brief 获取Tick数据
	 * 
	 * @param stdCode 标准合约代码
	 * @param count 数据条数
	 * @return Tick数据切片
	 */
	virtual WTSTickSlice* stra_get_ticks(const char* stdCode, uint32_t count) override;

	/**
	 * @brief 获取委托明细数据
	 * 
	 * @param stdCode 标准合约代码
	 * @param count 数据条数
	 * @return 委托明细数据切片
	 */
	virtual WTSOrdDtlSlice*	stra_get_order_detail(const char* stdCode, uint32_t count) override;

	/**
	 * @brief 获取委托队列数据
	 * 
	 * @param stdCode 标准合约代码
	 * @param count 数据条数
	 * @return 委托队列数据切片
	 */
	virtual WTSOrdQueSlice*	stra_get_order_queue(const char* stdCode, uint32_t count) override;

	/**
	 * @brief 获取成交明细数据
	 * 
	 * @param stdCode 标准合约代码
	 * @param count 数据条数
	 * @return 成交明细数据切片
	 */
	virtual WTSTransSlice*	stra_get_transaction(const char* stdCode, uint32_t count) override;

	/**
	 * @brief 获取最新Tick
	 * 
	 * @param stdCode 标准合约代码
	 * @return 最新Tick数据
	 */
	virtual WTSTickData* stra_get_last_tick(const char* stdCode) override;

	/**
	 * @brief 输出信息日志
	 * 
	 * @param message 日志消息
	 */
	virtual void stra_log_info(const char* message) override;
	
	/**
	 * @brief 输出调试日志
	 * 
	 * @param message 日志消息
	 */
	virtual void stra_log_debug(const char* message) override;
	
	/**
	 * @brief 输出错误日志
	 * 
	 * @param message 日志消息
	 */
	virtual void stra_log_error(const char* message) override;

	/**
	 * @brief 获取持仓
	 * 
	 * @param stdCode 标准合约代码
	 * @param bOnlyValid 是否只获取有效持仓
	 * @return 持仓数量
	 */
	virtual double stra_get_position(const char* stdCode, bool bOnlyValid = false) override;
	
	/**
	 * @brief 获取持仓盈亏
	 * 
	 * @param stdCode 标准合约代码
	 * @return 持仓盈亏
	 */
	virtual double stra_get_position_profit(const char* stdCode) override;
	
	/**
	 * @brief 获取价格
	 * 
	 * @param stdCode 标准合约代码
	 * @return 当前价格
	 */
	virtual double stra_get_price(const char* stdCode) override;
	
	/**
	 * @brief 获取未完成订单数量
	 * 
	 * @param stdCode 标准合约代码
	 * @return 未完成订单数量
	 */
	virtual double stra_get_undone(const char* stdCode) override;

	/**
	 * @brief 获取日期
	 * 
	 * @return 当前日期
	 */
	virtual uint32_t stra_get_date() override;
	
	/**
	 * @brief 获取时间
	 * 
	 * @return 当前时间
	 */
	virtual uint32_t stra_get_time() override;
	
	/**
	 * @brief 获取秒数
	 * 
	 * @return 当前秒数
	 */
	virtual uint32_t stra_get_secs() override;

	/**
	 * @brief 订阅Tick数据
	 * 
	 * @param stdCode 标准合约代码
	 */
	virtual void stra_sub_ticks(const char* stdCode) override;
	
	/**
	 * @brief 订阅委托明细数据
	 * 
	 * @param stdCode 标准合约代码
	 */
	virtual void stra_sub_order_details(const char* stdCode) override;
	
	/**
	 * @brief 订阅委托队列数据
	 * 
	 * @param stdCode 标准合约代码
	 */
	virtual void stra_sub_order_queues(const char* stdCode) override;
	
	/**
	 * @brief 订阅成交明细数据
	 * 
	 * @param stdCode 标准合约代码
	 */
	virtual void stra_sub_transactions(const char* stdCode) override;

	/**
	 * @brief 保存用户数据
	 * 
	 * @param key 键名
	 * @param val 键值
	 */
	virtual void stra_save_user_data(const char* key, const char* val) override;

	/**
	 * @brief 读取用户数据
	 * 
	 * @param key 键名
	 * @param defVal 默认值
	 * @return 键值
	 */
	virtual const char* stra_load_user_data(const char* key, const char* defVal = "") override;

	//////////////////////////////////////////////////////////////////////////
	// ITrdNotifySink 接口
	/**
	 * @brief 成交回调
	 * 
	 * @param localid 本地订单ID
	 * @param stdCode 标准合约代码
	 * @param isBuy 是否买入
	 * @param vol 成交数量
	 * @param price 成交价格
	 */
	virtual void on_trade(uint32_t localid, const char* stdCode, bool isBuy, double vol, double price) override;

	/**
	 * @brief 订单回调
	 * 
	 * @param localid 本地订单ID
	 * @param stdCode 标准合约代码
	 * @param isBuy 是否买入
	 * @param totalQty 总数量
	 * @param leftQty 剩余数量
	 * @param price 订单价格
	 * @param isCanceled 是否已撤销
	 */
	virtual void on_order(uint32_t localid, const char* stdCode, bool isBuy, double totalQty, double leftQty, double price, bool isCanceled) override;

	/**
	 * @brief 通道就绪回调
	 */
	virtual void on_channel_ready() override;

	/**
	 * @brief 通道丢失回调
	 */
	virtual void on_channel_lost() override;

	/**
	 * @brief 委托回调
	 * 
	 * @param localid 本地订单ID
	 * @param stdCode 标准合约代码
	 * @param bSuccess 是否成功
	 * @param message 消息
	 */
	virtual void on_entrust(uint32_t localid, const char* stdCode, bool bSuccess, const char* message) override;

	/**
	 * @brief 持仓回调
	 * 
	 * @param stdCode 标准合约代码
	 * @param isLong 是否多头
	 * @param prevol 前持仓数量
	 * @param preavail 前可用数量
	 * @param newvol 新持仓数量
	 * @param newavail 新可用数量
	 * @param tradingday 交易日
	 */
	virtual void on_position(const char* stdCode, bool isLong, double prevol, double preavail, double newvol, double newavail, uint32_t tradingday) override;

private:
	/**
	 * @brief 调试日志模板函数
	 * 
	 * @tparam Args 参数类型
	 * @param format 格式字符串
	 * @param args 参数列表
	 */
	template<typename... Args>
	void log_debug(const char* format, const Args& ...args)
	{
		std::string s = fmt::sprintf(format, args...);
		stra_log_debug(s.c_str());
	}

	/**
	 * @brief 信息日志模板函数
	 * 
	 * @tparam Args 参数类型
	 * @param format 格式字符串
	 * @param args 参数列表
	 */
	template<typename... Args>
	void log_info(const char* format, const Args& ...args)
	{
		std::string s = fmt::sprintf(format, args...);
		stra_log_info(s.c_str());
	}

	/**
	 * @brief 错误日志模板函数
	 * 
	 * @tparam Args 参数类型
	 * @param format 格式字符串
	 * @param args 参数列表
	 */
	template<typename... Args>
	void log_error(const char* format, const Args& ...args)
	{
		std::string s = fmt::sprintf(format, args...);
		stra_log_error(s.c_str());
	}

protected:
	/**
	 * @brief 获取内部合约代码
	 * 
	 * @param stdCode 标准合约代码
	 * @return 内部合约代码
	 */
	const char* get_inner_code(const char* stdCode);

	/**
	 * @brief 加载用户数据
	 */
	void	load_userdata();
	
	/**
	 * @brief 保存用户数据
	 */
	void	save_userdata();

	/**
	 * @brief 初始化输出文件
	 */
	void	init_outputs();

	/**
	 * @brief 执行设置仓位操作
	 * 
	 * @param stdCode 标准合约代码
	 * @param qty 目标数量
	 * @param price 价格
	 * @param userTag 用户标签
	 */
	void	do_set_position(const char* stdCode, double qty, double price = 0.0, const char* userTag = "");
	
	/**
	 * @brief 更新动态盈亏
	 * 
	 * @param stdCode 标准合约代码
	 * @param newTick 新Tick数据
	 */
	void	update_dyn_profit(const char* stdCode, WTSTickData* newTick);

	/**
	 * @brief 记录交易日志
	 * 
	 * @param stdCode 标准合约代码
	 * @param isLong 是否多头
	 * @param isOpen 是否开仓
	 * @param curTime 当前时间
	 * @param price 成交价格
	 * @param qty 成交数量
	 * @param fee 手续费
	 * @param userTag 用户标签
	 */
	inline void	log_trade(const char* stdCode, bool isLong, bool isOpen, uint64_t curTime, double price, double qty, double fee, const char* userTag);
	
	/**
	 * @brief 记录平仓日志
	 * 
	 * @param stdCode 标准合约代码
	 * @param isLong 是否多头
	 * @param openTime 开仓时间
	 * @param openpx 开仓价格
	 * @param closeTime 平仓时间
	 * @param closepx 平仓价格
	 * @param qty 平仓数量
	 * @param profit 本次盈亏
	 * @param maxprofit 最大盈利
	 * @param maxloss 最大亏损
	 * @param totalprofit 总盈亏
	 * @param enterTag 开仓标签
	 * @param exitTag 平仓标签
	 */
	inline void	log_close(const char* stdCode, bool isLong, uint64_t openTime, double openpx, uint64_t closeTime, double closepx, double qty,
		double profit, double maxprofit, double maxloss, double totalprofit, const char* enterTag, const char* exitTag);

	/**
	 * @brief 获取订单标签
	 * 
	 * @param localid 本地订单ID
	 * @return 订单标签
	 */
	inline const char* getOrderTag(uint32_t localid)
	{
		thread_local static OrderTag oTag;
		oTag._localid = localid;
		auto it = std::lower_bound(_orders.begin(), _orders.end(), oTag, [](const OrderTag& a, const OrderTag& b) {
			return a._localid < b._localid;
		});

		if (it == _orders.end())
			return "";

		return (*it)._usertag;
	}

	/**
	 * @brief 设置用户标签
	 * 
	 * @param localid 本地订单ID
	 * @param usertag 用户标签
	 */
	inline void setUserTag(uint32_t localid, const char* usertag)
	{
		_orders.push_back({ localid, usertag });
	}

	/**
	 * @brief 删除订单标签
	 * 
	 * @param localid 本地订单ID
	 */
	inline void eraseOrderTag(uint32_t localid)
	{
		thread_local static OrderTag oTag;
		oTag._localid = localid;
		auto it = std::lower_bound(_orders.begin(), _orders.end(), oTag, [](const OrderTag& a, const OrderTag& b) {
			return a._localid < b._localid;
		});

		if (it == _orders.end())
			return;

		_orders.erase(it);
	}

protected:
	uint32_t		_context_id;		/**< 上下文ID */
	WtHftEngine*	_engine;			/**< HFT引擎指针 */
	TraderAdapter*	_trader;			/**< 交易适配器指针 */

	faster_hashmap<LongKey, std::string> _code_map;	/**< 合约代码映射表 */

	BoostFilePtr	_sig_logs;			/**< 信号日志文件 */
	BoostFilePtr	_close_logs;		/**< 平仓日志文件 */
	BoostFilePtr	_trade_logs;		/**< 交易日志文件 */
	BoostFilePtr	_fund_logs;			/**< 资金日志文件 */

	//用户数据
	typedef faster_hashmap<LongKey, std::string> StringHashMap;
	StringHashMap	_user_datas;		/**< 用户数据映射表 */
	bool			_ud_modified;		/**< 用户数据是否已修改 */

	bool			_data_agent;		/**< 是否数据代理 */

	//tick订阅列表
	faster_hashset<LongKey> _tick_subs;	/**< Tick订阅集合 */

private:
	/**
	 * @struct _DetailInfo
	 * @brief 持仓明细信息结构体
	 */
	typedef struct _DetailInfo
	{
		bool		_long;				/**< 是否多头 */
		double		_price;				/**< 开仓价格 */
		double		_volume;			/**< 持仓数量 */
		uint64_t	_opentime;			/**< 开仓时间 */
		uint32_t	_opentdate;			/**< 开仓交易日 */
		double		_max_profit;		/**< 最大盈利 */
		double		_max_loss;			/**< 最大亏损 */
		double		_profit;			/**< 当前盈亏 */
		char		_usertag[32];		/**< 用户标签 */

		_DetailInfo()
		{
			memset(this, 0, sizeof(_DetailInfo));
		}
	} DetailInfo;

	/**
	 * @struct _PosInfo
	 * @brief 持仓信息结构体
	 */
	typedef struct _PosInfo
	{
		double		_volume;			/**< 持仓数量 */
		double		_closeprofit;		/**< 平仓盈亏 */
		double		_dynprofit;			/**< 动态盈亏 */

		std::vector<DetailInfo> _details;	/**< 持仓明细列表 */

		_PosInfo()
		{
			_volume = 0;
			_closeprofit = 0;
			_dynprofit = 0;
		}
	} PosInfo;
	typedef faster_hashmap<LongKey, PosInfo> PositionMap;
	PositionMap		_pos_map;			/**< 持仓映射表 */

	/**
	 * @struct _OrderTag
	 * @brief 订单标签结构体
	 */
	typedef struct _OrderTag
	{
		uint32_t	_localid;			/**< 本地订单ID */
		char		_usertag[64] = { 0 };	/**< 用户标签 */

		_OrderTag(){}
		_OrderTag(uint32_t localid, const char* usertag)
		{
			_localid = localid;
			wt_strcpy(_usertag, usertag);
		}
	} OrderTag;
	//typedef faster_hashmap<uint32_t, LongKey> OrderMap;
	//OrderMap		_orders;
	boost::circular_buffer<OrderTag> _orders;	/**< 订单标签循环缓冲区 */

	/**
	 * @struct _StraFundInfo
	 * @brief 策略资金信息结构体
	 */
	typedef struct _StraFundInfo
	{
		double	_total_profit;			/**< 总盈亏 */
		double	_total_dynprofit;		/**< 总动态盈亏 */
		double	_total_fees;			/**< 总手续费 */

		_StraFundInfo()
		{
			memset(this, 0, sizeof(_StraFundInfo));
		}
	} StraFundInfo;

	StraFundInfo		_fund_info;		/**< 策略资金信息 */

	typedef faster_hashmap<LongKey, double> PriceMap;
	PriceMap		_price_map;			/**< 价格映射表 */
};

NS_WTP_END
